package com.fishbone.file.minio;

import com.fishbone.file.config.MinProperties;
import io.minio.CopyConditions;
import io.minio.PutObjectOptions;
import io.minio.errors.*;
import io.minio.messages.Part;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import sun.nio.ch.FileChannelImpl;

import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;


/**
 * @ClassName FishBoneMinClient
 * @Author huyaxi
 * @DATE 2020/4/20 16:38
 */
@Slf4j
public class MinClient {

    private HssMinClient minioClient;

    public MinClient(MinProperties properties) throws Exception {
        this.minioClient = new HssMinClient(properties.getEndpoint(),properties.getAk(),properties.getSk());
    }


    /**
     * 创建桶
     * @param bucketName
     */
    public void createBucket(String bucketName) {
        try {
            minioClient.makeBucket(bucketName);
        } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) {
            log.error("bucket create error:{},cause:{}",e.getMessage(),e.getCause());
        }
    }


    /**
     * 判断桶是否存在
     * @param bucketName
     * @return
     */
    public boolean isBucketExist(String bucketName){
        try {
            return minioClient.bucketExists(bucketName);
        }catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e){
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
        }
        return false;
    }


    /**
     * 文件上传
     * @param bucketName
     * @param objectKey
     * @param inputStream
     */
    @SneakyThrows
    public void putObject(String bucketName, String objectKey, InputStream inputStream,String contentType){
        PutObjectOptions options = new PutObjectOptions(inputStream.available(),PutObjectOptions.MIN_MULTIPART_SIZE);
        options.setContentType(contentType);
        this.putObject(bucketName, objectKey, inputStream,options);
    }


    /**
     * 文件上传
     * @param bucketName
     * @param objectKey
     * @param file
     */
    public void putObject(String bucketName, String objectKey, File file,String contentType) {
        PutObjectOptions options = new PutObjectOptions(file.length(),PutObjectOptions.MIN_MULTIPART_SIZE);
        options.setContentType(contentType);
        this.putObject(bucketName, objectKey, file,options);
    }


    /**
     * 文件上传
     * @param bucketName
     * @param objectKey
     * @param file
     * @param objectOptions
     */
    public void putObject(String bucketName, String objectKey, File file, PutObjectOptions objectOptions) {
        try(FileInputStream inputStream = new FileInputStream(file)) {
            minioClient.putObject(bucketName, objectKey, inputStream, objectOptions);
        } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) {
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
        }
    }


    /**
     * 文件上传
     * @param bucketName
     * @param objectKey
     * @param inputStream
     * @param objectOptions
     */
    public void putObject(String bucketName, String objectKey, InputStream inputStream, PutObjectOptions objectOptions) {
        try {
            minioClient.putObject(bucketName, objectKey, inputStream, objectOptions);
        } catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e) {
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
        }
    }



    @SneakyThrows
    public void putObject(String bucketName, String objectName, Object data,Long objectSize,String contentType, ExecutorService service) {
        PutObjectOptions options = new PutObjectOptions(objectSize,PutObjectOptions.MIN_MULTIPART_SIZE);
        options.setContentType(contentType);
        minioClient.putObject(bucketName,objectName,options,data,service);
    }



    public String getObjectUrl(String bucketName, String objectKey) {
        try {
            return minioClient.getObjectUrl(bucketName, objectKey);
        } catch (Exception e) {
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
            return null;
        }
    }


    public InputStream getObject(String bucketName, String objectKey) {
        try {
            return minioClient.getObject(bucketName, objectKey);
        } catch (Exception e) {
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
            return null;
        }
    }


    /**
     * 删除桶
     * @param bucketName
     */
    public void deleteBucket(String bucketName) {
        try {
            minioClient.removeBucket(bucketName);
        }catch (MinioException | NoSuchAlgorithmException | IOException | InvalidKeyException e){
            log.error("server error:{},cause:{}",e.getMessage(),e.getCause());
        }
    }


    /**
     * 分片上传uploadId
     * @param bucketName
     * @param objectKey
     * @return
     */
    public String initMultipartUpload(String bucketName,String objectKey) {
        return minioClient.initMultipartUpload(bucketName,objectKey,new HashMap<>(16));
    }


    /**
     * 上传分片
     * @param bucketName
     * @param objectName
     * @param data
     * @param length
     * @param uploadId
     * @param partNumber
     * @return
     */
    public String uploadPartFile(String bucketName, String objectName, Object data, int length, String uploadId, int partNumber) {
        return minioClient.uploadPartFile(bucketName,objectName,data,length,uploadId,partNumber,new HashMap<>());
    }


    /**
     * 合并分片
     * @param bucketName
     * @param objectName
     * @param uploadId
     * @param parts
     */
    public void completeMultipartUploadFile(String bucketName, String objectName, String uploadId, Part[] parts) {
        minioClient.completeMultipartUploadFile(bucketName,objectName,uploadId,parts);
    }
}

